# coding: utf8
"""
实用工具
:author: Unknown 20150707
"""
__author__ = 'TonyGuo'

from django.utils import timezone

# 当前时区
LOCAL_TIMEZONE = timezone.get_current_timezone()

# UTC时区
UTC_TIMEZONE = timezone.utc

# 标注时间格式
STANDARD_TIME_FORMATTER = '%Y-%m-%d %H:%M:%S'


def parse_local(time_str, formatter=STANDARD_TIME_FORMATTER):
    """
    以local时区从字符串中解析出datetime
    :param time_str: 时间字串
    :param formatter: 字串格式
    :return: local datetime
    :rtype: datetime
    :author: Unknown 20150707
    """
    dt = timezone.datetime.strptime(time_str, formatter)
    return timezone.make_aware(dt, LOCAL_TIMEZONE)


def parse_utc(time_str, formatter=STANDARD_TIME_FORMATTER):
    """
    以utc时区从字符串中解析出datetime
    :param time_str: 时间字串
    :param formatter: 字串格式
    :return: utc datetime
    :rtype: datetime
    :author: Unknown 20150707
    """
    dt = timezone.datetime.strptime(time_str, formatter)
    return timezone.make_aware(dt, UTC_TIMEZONE)


def dumps_to(dt, formatter=STANDARD_TIME_FORMATTER):
    """
    将datetime转换成指定格式的字符串
    :param dt: <datetime>
    :param formatter: <str: 时间格式字符串>
    :return: <str: 格式化后的时间字符串>
    :author: gzj 20150714
    """
    return dt.strftime(formatter)


def to_local(dt):
    """
    将目标时间转为本地时间
    :param dt: 目标时间
    :return: 本地时间
    :rtype: datetime
    :author: Unknown 20150707
    """
    return timezone.localtime(dt, LOCAL_TIMEZONE)


def to_utc(dt):
    """
    将目标时间转为UTC时间
    :param dt: 目标时间
    :return: utc时间
    :rtype: datetime
    :author: Unknown 20150707
    """
    return timezone.localtime(dt, UTC_TIMEZONE)


def now_utc():
    """
    :return: utc时间
    :rtype: datetime
    :author: Unknown 20150707
    """
    return timezone.now()


def now_local():
    """
    :return: 本地时间
    :rtype: datetime
    :author: Unknown 20150707
    """
    return to_local(now_utc())


def get_week_range(dst_dt=None, utc=True):
    """
    获得目标local日期所在周的区间
    :param dst_dt: 目标local日期，默认为今天
    :param utc: 是否返回utc日期
    :return: [first_datetime, last_datetime]
    :rtype: list
    :author: Unknown @ 20150512
    """
    if not dst_dt:
        dst_dt = now_local()
    else:
        dst_dt = to_local(dst_dt)
    first_dt = dst_dt - timezone.timedelta(dst_dt.weekday())
    first_dt = timezone.datetime(first_dt.year, first_dt.month, first_dt.day, 0, 0, 0, tzinfo=first_dt.tzinfo)
    last_dt = dst_dt + timezone.timedelta(6 - dst_dt.weekday())
    last_dt = timezone.datetime(last_dt.year, last_dt.month, last_dt.day, 23, 59, 59, tzinfo=last_dt.tzinfo)
    if utc:
        first_dt = to_utc(first_dt)
        last_dt = to_utc(last_dt)
    return first_dt, last_dt


def get_month_range(dst_dt=None, utc=True):
    """
    获得目标local日期所在月的区间
    :param dst_dt: 目标local日期，默认为今天
    :param utc: 是否返回utc时间
    :return: [first_datetime, last_datetime]
    :rtype: list
    :author: Unknown @ 20150512
    """
    import calendar
    if not dst_dt:
        dst_dt = now_local()
    else:
        dst_dt = to_local(dst_dt)
    first_dt = timezone.datetime(dst_dt.year, dst_dt.month, 1, 0, 0, 0, tzinfo=dst_dt.tzinfo)
    end_day = calendar.monthrange(dst_dt.year, dst_dt.month)[1]
    last_dt = timezone.datetime(dst_dt.year, dst_dt.month, end_day, 23, 59, 59, tzinfo=dst_dt.tzinfo)
    if utc:
        first_dt = to_utc(first_dt)
        last_dt = to_utc(last_dt)
    return first_dt, last_dt


def get_day_range(dst_dt=None, utc=True):
    """
    获得目标local日期所在日的区间
    :param dst_dt: 目标local日期，默认为今天
    :param utc: 是否返回utc时间, 否则返回local时间
    :return: [first_datetime, last_datetime]
    :rtype: list
    :author: Unknown @ 20150512
    """
    if not dst_dt:
        dst_dt = now_local()
    else:
        dst_dt = to_local(dst_dt)
    first_dt = timezone.datetime(dst_dt.year, dst_dt.month, dst_dt.day, 0, 0, 0, tzinfo=dst_dt.tzinfo)
    last_dt = timezone.datetime(dst_dt.year, dst_dt.month, dst_dt.day, 23, 59, 59, tzinfo=dst_dt.tzinfo)
    if utc:
        first_dt = to_utc(first_dt)
        last_dt = to_utc(last_dt)
    return first_dt, last_dt


def get_last_week_range(dst_dt=None, utc=True):
    """
    获取目标local日期上一周的区间
    :param dst_dt: 目标local日期， 默认为今天
    :param utc: 是否返回utc时间
    :return: [first_datetime, last_datetime]
    :rtype: list
    :author: Unknown @ 20150512
    """
    if not dst_dt:
        dst_dt = now_local()
    else:
        dst_dt = to_local(dst_dt)
    return get_week_range(get_week_range(dst_dt, utc=False)[0] - timezone.timedelta(days=1), utc)


def get_next_time(src_dt, days=0, hours=0, minutes=0, seconds=0, milliseconds=0):
    """
    获取指定间隔的下一个时间戳
    :param src_dt: <datetime: 原时间>
    :param days: <int: 间隔天数>
    :param hours: <int: 间隔小时数>
    :param minutes: <int: 间隔分钟数>
    :param seconds: <int: 间隔秒数>
    :param milliseconds: <int: 间隔毫秒数>
    :return: <datetime: 下一个时间戳>
    """
    return src_dt + timezone.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds, milliseconds=milliseconds)